using System;
using System.Net.Sockets;
using System.Text;
using UnityEngine;

/*
 * LengthPrefixSocketManager - 基于长度前缀的Socket管理器
 * 
 * 功能：
 * 1. 使用消息长度作为前缀来分割消息
 * 2. 处理不完整消息的拼接
 * 3. 实现基于长度前缀的消息确认机制
 * 
 * 版本：1.0
 * 作者：yixiang.hui
 * 创建时间：2025.9.4
 * 最后修改：2025.9.4
 */

namespace HyxFrame.Core
{
    /// <summary>
    /// 基于长度前缀的Socket管理器，使用消息长度作为前缀来分割消息
    /// </summary>
    public class LengthPrefixSocketManager : SocketManagerBase
    {
        #region 常量定义
        
        /// <summary>
        /// 长度前缀的大小（字节）
        /// </summary>
        private const int LENGTH_PREFIX_SIZE = 4;
        
        #endregion
        
        #region 私有字段
        
        /// <summary>
        /// 当前消息缓冲区
        /// </summary>
        private byte[] currentMessageBuffer;
        
        /// <summary>
        /// 当前已接收字节数
        /// </summary>
        private int currentReceivedBytes = 0;
        
        /// <summary>
        /// 消息总长度
        /// </summary>
        private int messageTotalLength = 0;
        
        #endregion
        
        #region 消息处理实现
        
        /// <summary>
        /// 处理接收到的数据，解析长度前缀并提取完整消息
        /// </summary>
        /// <param name="data">接收到的字节数组</param>
        /// <param name="bytesRead">实际读取的字节数</param>
        protected override void ProcessReceivedData(byte[] data, int bytesRead)
        {
            int offset = 0;
            
            while (offset < bytesRead)
            {
                if (messageTotalLength == 0)
                {
                    // 读取长度前缀
                    if (bytesRead - offset >= LENGTH_PREFIX_SIZE)
                    {
                        messageTotalLength = BitConverter.ToInt32(data, offset);
                        offset += LENGTH_PREFIX_SIZE;
                        
                        // 创建消息缓冲区
                        currentMessageBuffer = new byte[messageTotalLength];
                        currentReceivedBytes = 0;
                    }
                    else
                    {
                        break; // 数据不足，等待更多数据
                    }
                }
                
                if (messageTotalLength > 0)
                {
                    // 计算需要读取的字节数
                    int bytesToRead = Math.Min(messageTotalLength - currentReceivedBytes, bytesRead - offset);
                    
                    // 复制数据到消息缓冲区
                    Buffer.BlockCopy(data, offset, currentMessageBuffer, currentReceivedBytes, bytesToRead);
                    
                    offset += bytesToRead;
                    currentReceivedBytes += bytesToRead;
                    
                    // 检查是否已接收完整消息
                    if (currentReceivedBytes == messageTotalLength)
                    {
                        // 将字节数组转换为字符串
                        string fullMessage = Encoding.UTF8.GetString(currentMessageBuffer);
                        
                        // 处理消息类型
                        if (fullMessage.StartsWith("ACK:"))
                        {
                            HandleAcknowledgment(fullMessage);
                        }
                        else
                        {
                            HandleMessage(fullMessage);
                            SendAcknowledgment(fullMessage);
                        }
                        
                        // 重置状态，准备接收下一条消息
                        messageTotalLength = 0;
                        currentMessageBuffer = null;
                        currentReceivedBytes = 0;
                    }
                }
            }
        }
        
        /// <summary>
        /// 格式化发送消息，添加长度前缀
        /// </summary>
        /// <param name="message">原始消息</param>
        /// <param name="messageId">消息ID</param>
        /// <returns>格式化后的字节数组</returns>
        protected override byte[] FormatSendMessage(string message, int messageId)
        {
            string content = $"{messageId}:{message}";
            byte[] contentBytes = Encoding.UTF8.GetBytes(content);
            
            // 添加长度前缀
            byte[] lengthPrefix = BitConverter.GetBytes(contentBytes.Length);
            byte[] fullMessage = new byte[LENGTH_PREFIX_SIZE + contentBytes.Length];
            
            // 组合长度前缀和消息内容
            Buffer.BlockCopy(lengthPrefix, 0, fullMessage, 0, LENGTH_PREFIX_SIZE);
            Buffer.BlockCopy(contentBytes, 0, fullMessage, LENGTH_PREFIX_SIZE, contentBytes.Length);
            
            return fullMessage;
        }
        
        /// <summary>
        /// 发送确认消息
        /// </summary>
        /// <param name="message">需要确认的原始消息</param>
        protected override void SendAcknowledgment(string message)
        {
            try
            {
                string[] parts = message.Split(':');
                if (parts.Length >= 1 && int.TryParse(parts[0], out int messageId))
                {
                    string ackMessage = $"ACK:{messageId}";
                    byte[] ackBytes = Encoding.UTF8.GetBytes(ackMessage);
                    
                    // 添加长度前缀
                    byte[] lengthPrefix = BitConverter.GetBytes(ackBytes.Length);
                    byte[] fullAck = new byte[LENGTH_PREFIX_SIZE + ackBytes.Length];
                    
                    // 组合长度前缀和确认消息
                    Buffer.BlockCopy(lengthPrefix, 0, fullAck, 0, LENGTH_PREFIX_SIZE);
                    Buffer.BlockCopy(ackBytes, 0, fullAck, LENGTH_PREFIX_SIZE, ackBytes.Length);
                    
                    // 异步发送确认消息
                    socket.BeginSend(fullAck, 0, fullAck.Length, SocketFlags.None, null, socket);
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"发送确认失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 处理接收到的消息
        /// </summary>
        /// <param name="acknowledgment">消息内容</param>
        protected override void HandleMessage(string acknowledgment)
        {
            base.HandleMessage(acknowledgment);
            Debug.Log($"接收到完整消息: {acknowledgment}");
        }
        
        #endregion
    }
}